/**
 * @author 严琼
 * @date 2019/9/18
 * @Description: 校验公共方法
*/

// 手机
let mobileReg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/

// 电话
let phoneReg = /^([0-9]{3,4}-)?[0-9]{7,8}$/

// 必须为数字
let numberReg = /^\d+$|^\d+[.]?\d+$/

// 必须为整数
let intReg = /^[0-9]*$/

// 必须为整数(不为0)
let intNoZeroReg = /^[1-9]\d*(\.\d+)?$/

// 密码
let passwordReg = /^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$)([^\u4e00-\u9fa5\s]){6,20}$/

// 联系人
let contactsReg = /^[\u0391-\uFFE5A-Za-z]+$/

// 身份证号
let regId = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/

// 邮箱
let emailReg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/

// 小写字母
let lowercaseReg = /^[a-z]+$/

// 大写字母
let capitalReg = /^[A-Z]+$/

// 大小写字母
let upperAndLowerReg = /^[A-Za-z]+$/

// 整数和英文
let intAndAbcReg = /(^[A-Za-z0-9]+$)/

function getByteLen(val) {
  var len = 0;
  for (var i = 0; i < val.length; i++) {
    var c = val.charCodeAt(i);
    if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) { 
      len++; 
    }
    else { 
      len+=2; // 中文算两个字符默认
    } 
  }
  return len;
}

let FormValidate = (function () {
  function FormValidate () {}
  // From表单验证规则  可用于公用的校验部分
  FormValidate.Form = function () {
    return {
      // 不能为0
      validateNoZero (rule, value, callback) {
        if (value !== '') {
          if (parseInt(value) == 0) {
            if (rule.message) {
              callback(new Error(rule.message))
            }else{
              callback(new Error('不能为0'))
            }
          } else {
            callback()
          }
        } else {
          callback()
        }
      },

      // 只能数字的验证
      validateNumber (rule, value, callback) {
        if (value !== '') {
          if (!numberReg.test(value)) {
            callback(new Error('必须为数字'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },

      // 整数的验证 
      validateInt (rule, value, callback) {
        if (value !== '') {
          if (!intReg.test(value)) {
            if (rule.message) {
              callback(new Error(rule.message))
            }else{
              callback(new Error('必须为整数'))
            }
          } else {
            if (typeof rule.max !== 'undefined' && typeof rule.min !== 'undefined') {
              if (!(parseInt(value) <= parseInt(rule.max) && parseInt(value) >= parseInt(rule.min))) {
                if (rule.message) {
                  callback(new Error(rule.message))
                }else{
                  return callback(new Error('整数数值最小为' + rule.min + '最大为' + rule.max))
                }
              } else {
                callback()
              }
            } else if (typeof rule.max !== 'undefined' && typeof rule.min === 'undefined') {
              if (!(parseInt(value) <= parseInt(rule.max) && parseInt(value) >= 0)) {
                if (rule.message) {
                  callback(new Error(rule.message))
                }else{
                  return callback(new Error('整数数值最大为' + rule.max))
                }
              } else {
                callback()
              }
            } else if (typeof rule.max === 'undefined' && typeof rule.min !== 'undefined') {
              if (!(parseInt(value) >= parseInt(rule.min))) {
                if (rule.message) {
                  callback(new Error(rule.message))
                }else{
                  return callback(new Error('整数数值最小为' + rule.min))
                }               
              } else {
                callback()
              }
            } else {
              callback()
            }
          }
        } else {
          callback()
        }
      },
     
      // 整数大于0的验证 
      validateIntNoZero (rule, value, callback) {
        if (value !== '') {
          if (!intNoZeroReg.test(value)) {
            if (rule.message) {
              callback(new Error(rule.message))
            }else{
              callback(new Error('必须为大于0的整数'))
            }
          } else {
            if (typeof rule.max !== 'undefined' && typeof rule.min !== 'undefined') {
              if (!(parseInt(value) <= parseInt(rule.max) && parseInt(value) >= parseInt(rule.min))) {
                if (rule.message) {
                  callback(new Error(rule.message))
                }else{
                  return callback(new Error('整数数值最小为' + rule.min + '最大为' + rule.max))
                }
              } else {
                callback()
              }
            } else if (typeof rule.max !== 'undefined' && typeof rule.min === 'undefined') {
              if (!(parseInt(value) <= parseInt(rule.max) && parseInt(value) >= 0)) {
                if (rule.message) {
                  callback(new Error(rule.message))
                }else{
                  return callback(new Error('整数数值最小为1，最大为' + rule.max))
                }
              } else {
                callback()
              }
            } else if (typeof rule.max === 'undefined' && typeof rule.min !== 'undefined') {
              if (!(parseInt(value) >= parseInt(rule.min))) {
                if (rule.message) {
                  callback(new Error(rule.message))
                }else{
                  return callback(new Error('整数数值最小为' + rule.min))
                }  
              } else {
                callback()
              }
            } else {
              callback()
            }
          }
        } else {
          callback()
        }
      },

      // 无限位整数和小数
      // 1. 若更改小数点前限制位数，则更改 + （例如：小数点前限制4位——([^0][0-9]\d{0,3}|0) ），整数同理。
      // 2. 若更改小数点后限制位数，则更改 {1,2} （ 例如:：小数点后最多保留3位——{1, 3}；小数点后必须保留3位——{3} ）。
      validateDigit (rule, value, callback) {
        let reg = /^([0-9]\d*)(\.{0,1}\d*[0-9])?$/
        if (value !== '') {
          if (!reg.test(value)) {
            callback(new Error('必须为数字'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },
      
      // 小数校验，默认两位，rule.len可以控制校验几位小数
      validateTwoDecimal (rule, value, callback) {
        let reg = /^(0|([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/
        if (value !== '') {
          if (!reg.test(value)) {
            callback(new Error('只能输入数字，最多保留两位小数'))
          } else {
            if (typeof rule.max !== 'undefined' && typeof rule.min !== 'undefined') {
              if (!(parseFloat(value) <= parseFloat(rule.max) && parseFloat(value) >= parseFloat(rule.min))) {
                return callback(new Error(rule.message || ('数值最小为' + rule.min + '最大为' + rule.max)))
              } else {
                callback()
              }
            } else if (typeof rule.max !== 'undefined' && typeof rule.min === 'undefined') {
              if (!(parseFloat(value) <= parseFloat(rule.max) && parseFloat(value) >= 0)) {
                return callback(new Error(rule.message || ('数值最大为' + rule.max)))
              } else {
                callback()
              }
            } else if (typeof rule.max === 'undefined' && typeof rule.min !== 'undefined') {
              if (!(parseFloat(value) >= parseFloat(rule.min))) {
                return callback(new Error(rule.message || ('数值最小为' + rule.min)))
              } else {
                callback()
              }
            } else {
              callback()
            }
          }
        } else {
          callback()
        }
      },

      // 小数校验，默认四位，rule.len可以控制校验几位小数
      validateFourDecimal (rule, value, callback) {
        let reg = /^(0|([1-9][0-9]*)|(([0]\.\d{1,4}|[1-9][0-9]*\.\d{1,4})))$/
        if (value !== '') {
          if (!reg.test(value)) {
            callback(new Error('只能输入数字，最多保留四位小数点'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },

      // 小数校验，默认六位，rule.len可以控制校验几位小数
      validateSixDecimal (rule, value, callback) {
        let reg = /^(0|([1-9][0-9]*)|(([0]\.\d{1,6}|[1-9][0-9]*\.\d{1,6})))$/
        if (value !== '') {
          if (!reg.test(value)) {
            callback(new Error('只能输入数字，最多保留六位小数点'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },

      // 整数校验 len控制几位数，max最大几位数，min最小几位数
      validateNumLen (rule, value, callback) {
        var reg = ''
        // if (rule.len) {
        //   reg=new RegExp("^[0-9]{" + rule.len + "}$",'gi')
        // }
        // if (rule.max) {
        //   reg=new RegExp("^[0-9]{0," + rule.max + "}$",'gi')
        // }
        // if (rule.min) {
        //   reg=new RegExp("^[0-9]{" + rule.min + ",}$",'gi')
        // }
        // if (rule.min && rule.max) {
        //   reg=new RegExp("^[0-9]{" + rule.min + "," + rule.max + "}$",'gi')
        // }
        if (value !== '') {
          if (!reg.test(value)) {
            callback(new Error('只能输入数字，最多保留两位小数'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },

      // 密码的验证
      validatePsdReg (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!passwordReg.test(value)) {
          callback(new Error('请输入6-20位英文字母、数字或者符号（除空格），且字母、数字和标点符号至少包含两种'))
        } else {
          callback()
        }
      },

      // 联系人
      validateContacts (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!contactsReg.test(value)) {
          callback(new Error('不可输入特殊字符,只能输入汉字和字母'))
        } else {
          callback()
        }
      },

      // 邮箱的验证规则
      validateEmail (rule, value, callback) {
        if (value !== '') {
          if (!emailReg.test(value)) {
            callback(new Error('邮箱格式不正确'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },

      // 手机号码的验证
      validatemobile (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!mobileReg.test(value)) {
          callback(new Error('手机格式不正确'))
        } else {
          callback()
        }
      },

      // 电话号码的验证
      validatePhone (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!phoneReg.test(value)) {
          callback(new Error('电话号码格式不正确'))
        } else {
          callback()
        }
      },

      // 身份证的验证规则
      ID (rule, value, callback) {
        if (!value) {
          return callback()
        }
        //15位和18位身份证号码的正则表达式
        let flag = true
        let regIdCard = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/;
        //如果通过该验证，说明身份证格式正确，但准确性还需计算
        if (regIdCard.test(value) && regId.test(value)) {
          if (value.length == 18) {
            let idCardWi = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //将前17位加权因子保存在数组里
            let idCardY = new Array(1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2); //这是除以11后，可能产生的11位余数、验证码，也保存成数组
            let idCardWiSum = 0; //用来保存前17位各自乖以加权因子后的总和
            for (let i = 0; i < 17; i++) {
              idCardWiSum += value.substring(i, i + 1) * idCardWi[i];
            }
            let idCardMod = idCardWiSum % 11;//计算出校验码所在数组的位置
            let idCardLast = value.substring(17);//得到最后一位身份证号码
            //如果等于2，则说明校验码是10，身份证号码最后一位应该是X
            if (idCardMod == 2) {
              if (!(idCardLast == "X" || idCardLast == "x")) {//
                flag = false;
              }
            } else {
              //用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
              if (!(idCardLast == idCardY[idCardMod])) {
                flag = false;
              }
            }
          }
        } else {
          flag = false
        }
        // if (!regId.test(value)) {
        if (!flag) {
          callback(new Error('请输入正确的二代身份证号码'))
        } else {
          callback()
        }
      },

      // 小写字母的验证规则  
      lowercase (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!lowercaseReg.test(value)) {
          callback(new Error('请输入正确的小写字母'))
        } else {
          callback()
        }
      },

      // 大写字母的验证规则
      capital (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!capitalReg.test(value)) {
          callback(new Error('请输入正确的大写字母'))
        } else {
          callback()
        }
      },

      // 大小写字母的验证规则
      upperAndLower (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!upperAndLowerReg.test(value)) {
          callback(new Error('请输入正确的英文字符'))
        } else {
          callback()
        }
      },
     
      // 数字和英文的验证规则
      intAndAbc (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!intAndAbcReg.test(value)) {
          callback(new Error('只能输入数字和英文'))
        } else {
          callback()
        }
      },

       // 姓名
       validateName (rule, value, callback) {
        if (!value) {
          return callback()
        }
        if (!contactsReg.test(value)) {
          return callback(new Error('姓名不可输入特殊字符,只能输入汉字和字母'))
        }         
        var len = getByteLen(value)
        if (rule.max && rule.min) {
          if (!(len <= parseInt(rule.max) && len >= parseInt(rule.min))) {
            return callback(new Error('姓名长度最小为' + rule.min + ',最大为' + rule.max))
          }
        } else if (rule.max && !rule.min) {
          if (!(len <= parseInt(rule.max) && len >= 0)) {
            return callback(new Error('姓名长度最大为' + rule.max))
          }
        } else if (!rule.max && rule.min) {
          if (!(len >= parseInt(rule.min))) {
            return callback(new Error('姓名长度最小为' + rule.min))
          }
        }
        callback()
      },

      // 长度校验
      validateLen (rule, value, callback) {
        if (!value) {
          return callback()
        }       
        var len = getByteLen(value)
        if (rule.max && rule.min) {
          if (!(len <= parseInt(rule.max) && len >= parseInt(rule.min))) {
            return callback(new Error(rule.message || ('长度最小为' + rule.min + '最大为' + rule.max)))
          }
        } else if (rule.max && !rule.min) {
          if (!(len <= parseInt(rule.max) && len >= 0)) {
            return callback(new Error(rule.message || ('长度最大为' + rule.max)))
          }
        } else if (!rule.max && rule.min) {
          if (!(len >= parseInt(rule.min))) {
            return callback(new Error(rule.message || ('长度最小为' + rule.min)))
          }
        }
        callback()
      },

      // 根据iserror显示错误信息
      validateShowError (rule, value, callback) {
        if (!value || rule.message == '') {
          return callback()
        }       
        if (rule.isError) {
          return callback(new Error(rule.message))
        }
        callback()
      },

      /* 校验日期对比当前日期， 
        * nowDate: 'minEqual' 小于等于
        *          'maxEqual' 大于等于
        *          'min' 小于
        *          'max' 大于
      */

      validatedate (rule, value, callback) {
        if (!value) {
          return callback()
        }      
        let mydate = new Date();       
        let str = "" + mydate.getFullYear() + "-";
        str += (mydate.getMonth()+1) + "-";
        str += mydate.getDate();
        let nowdate = new Date(str);
        let valueDate = new Date(value)
        if (rule.hasOwnProperty('nowDate')) {
          switch (rule.nowDate) {
            case 'minEqual':
              if (valueDate > nowdate) {
                return callback(new Error(rule.message || ('所选日期应小于等于当前日期')))
              }
              break;
            case 'maxEqual':
              if (valueDate > nowdate) {
                return callback(new Error(rule.message || ('所选日期应大于等于当前日期')))
              }
              break;
            case 'min':
              if (valueDate >= nowdate) {
                return callback(new Error(rule.message || ('所选日期应小于当前日期')))
              }
              break;
            case 'max':
              if (valueDate <= nowdate) {
                return callback(new Error(rule.message || ('所选日期应大于当前日期')))
              }
              break;                      
            default:
              break;
          }
        }
        callback()
      }
    }
  }

  return FormValidate
}())

exports.FormValidate = FormValidate